﻿using System;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace CooBrowser
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private string currentPath = "";

        // Windows API for extracting system icons
        [DllImport("shell32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags);

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool DestroyIcon(IntPtr hIcon);

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct SHFILEINFO
        {
            public IntPtr hIcon;
            public int iIcon;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
            public string szDisplayName;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
            public string szTypeName;
            public uint dwAttributes;
        }

        public const uint SHGFI_ICON = 0x000000100;
        public const uint SHGFI_SMALLICON = 0x000000001;
        public const uint SHGFI_LARGEICON = 0x000000000;
        public const uint SHGFI_USEFILEATTRIBUTES = 0x000000010;
        public const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
        public const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;

        public MainWindow()
        {
            InitializeComponent();
            InitializeFolderTree();
            LoadDrivesInFileView(); // Load drives in the right panel initially
        }

        private void LoadDrivesInFileView()
        {
            try
            {
                var items = DriveInfo.GetDrives()
                    .Where(d => d.IsReady)
                    .Select(d => new FileSystemItem
                    {
                        Name = GetDriveLabel(d),
                        Type = "驱动器",
                        Icon = GetSystemIcon(d.Name, true),
                        Size = FormatFileSize(d.TotalSize),
                        Modified = "",
                        FullPath = d.Name,
                        IsDirectory = true
                    })
                    .ToList();

                FileListView.ItemsSource = items;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载驱动器时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void LoadDrives()
        {
            try
            {
                var driveItems = DriveInfo.GetDrives()
                    .Where(d => d.IsReady)
                    .Select(d => new DriveItem
                    {
                        Name = d.Name,
                        Label = GetDriveLabel(d),
                        Icon = GetSystemIcon(d.Name, true)
                    })
                    .ToList();
                
                // DrivesListBox 已被 FolderTreeView 替代
                // DrivesListBox.ItemsSource = driveItems;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载驱动器时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private string GetDriveLabel(DriveInfo drive)
        {
            string label = !string.IsNullOrEmpty(drive.VolumeLabel) ? drive.VolumeLabel : drive.DriveType.ToString();
            return $"{label} ({drive.Name.TrimEnd('\\')})";
        }

        // 此方法已被 FolderTreeView 相关事件处理程序替代
        private void DrivesListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // DrivesListBox 已被移除，此方法保留以供参考
            /*
            if (DrivesListBox.SelectedItem is DriveItem selectedDrive)
            {
                NavigateToPath(selectedDrive.Name);
            }
            */
        }

        private void PathTextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                NavigateToPath(PathTextBox.Text);
            }
        }

        private void GoButton_Click(object sender, RoutedEventArgs e)
        {
            NavigateToPath(PathTextBox.Text);
        }

        private void NavigateToPath(string path)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(path))
                    return;

                if (!Directory.Exists(path))
                {
                    MessageBox.Show($"Path does not exist: {path}", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                currentPath = path;
                PathTextBox.Text = currentPath;
                LoadDirectoryContents(currentPath);
                
                // Synchronize tree view selection with current path
                SyncTreeViewWithPath(path);
            }
            catch (UnauthorizedAccessException)
            {
                MessageBox.Show($"访问被拒绝: {path}", "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"导航到路径时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        
        private void InitializeFolderTree()
        {
            try
            {
                var rootItems = new ObservableCollection<FolderTreeItem>();
                
                // Add drives as root items
                foreach (var drive in DriveInfo.GetDrives().Where(d => d.IsReady))
                {
                    var driveItem = new FolderTreeItem
                    {
                        Name = GetDriveLabel(drive),
                        FullPath = drive.Name,
                        Icon = GetSystemIcon(drive.Name, true)
                    };
                    
                    rootItems.Add(driveItem);
                }
                
                FolderTreeView.ItemsSource = rootItems;
            }
            catch (Exception ex)
            {
                MessageBox.Show($"初始化文件夹树时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        
        private void TreeViewItem_Expanded(object sender, RoutedEventArgs e)
        {
            var treeViewItem = sender as TreeViewItem;
            var folderItem = treeViewItem?.DataContext as FolderTreeItem;
            
            if (folderItem != null && !folderItem.IsLoaded)
            {
                // Clear the dummy item
                folderItem.Children.Clear();
                
                // Load actual subfolders
                LoadSubfolders(folderItem);
                
                folderItem.IsLoaded = true;
            }
        }
        
        private void FolderTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (e.NewValue is FolderTreeItem selectedItem)
            {
                NavigateToPath(selectedItem.FullPath);
            }
        }
        
        private void SyncTreeViewWithPath(string path)
        {
            try
            {
                // Find the root drive item first
                string driveLetter = System.IO.Path.GetPathRoot(path) ?? "";
                
                if (string.IsNullOrEmpty(driveLetter))
                    return;
                    
                var rootItems = FolderTreeView.ItemsSource as ObservableCollection<FolderTreeItem>;
                if (rootItems == null)
                    return;
                
                // Find the matching drive
                FolderTreeItem targetDriveItem = null;
                foreach (var rootItem in rootItems)
                {
                    if (rootItem.FullPath.Equals(driveLetter, StringComparison.OrdinalIgnoreCase))
                    {
                        targetDriveItem = rootItem;
                        break;
                    }
                }
                
                if (targetDriveItem == null)
                    return;
                
                // If we're just navigating to the drive root, select it and return
                if (path.Equals(driveLetter, StringComparison.OrdinalIgnoreCase))
                {
                    var driveTreeViewItem = FolderTreeView.ItemContainerGenerator.ContainerFromItem(targetDriveItem) as TreeViewItem;
                    if (driveTreeViewItem != null)
                    {
                        driveTreeViewItem.IsSelected = true;
                        driveTreeViewItem.BringIntoView();
                    }
                    return;
                }
                
                // Get the path segments to navigate through
                string relativePath = path?.Substring(driveLetter?.Length ?? 0).TrimStart('\\') ?? string.Empty;
                string[] pathSegments = relativePath.Split('\\');
                
                // Ensure the drive node is expanded
                var driveItem = FolderTreeView.ItemContainerGenerator.ContainerFromItem(targetDriveItem) as TreeViewItem;
                if (driveItem != null)
                {
                    driveItem.IsExpanded = true;
                    
                    // Wait for the UI to update
                    Dispatcher.Invoke(() => { }, System.Windows.Threading.DispatcherPriority.Render);
                    
                    // Navigate through each path segment
                    FolderTreeItem currentItem = targetDriveItem;
                    TreeViewItem currentTreeItem = driveItem;
                    
                    foreach (var segment in pathSegments)
                    {
                        // Skip empty segments
                        if (string.IsNullOrEmpty(segment))
                            continue;
                            
                        // Make sure children are loaded
                        if (!currentItem.IsLoaded)
                        {
                            currentItem.Children.Clear();
                            LoadSubfolders(currentItem);
                            currentItem.IsLoaded = true;
                        }
                        
                        // Find the matching child
                        FolderTreeItem nextItem = null;
                        foreach (var child in currentItem.Children)
                        {
                            if (child.Name.Equals(segment, StringComparison.OrdinalIgnoreCase))
                            {
                                nextItem = child;
                                break;
                            }
                        }
                        
                        if (nextItem == null)
                            break;
                            
                        // Update current item and expand
                        currentItem = nextItem;
                        
                        // Get the TreeViewItem for this folder
                        currentTreeItem = currentTreeItem.ItemContainerGenerator.ContainerFromItem(currentItem) as TreeViewItem;
                        if (currentTreeItem == null)
                            break;
                            
                        // Expand if not the last segment
                        if (segment != pathSegments.Last())
                        {
                            currentTreeItem.IsExpanded = true;
                            // Wait for the UI to update
                            Dispatcher.Invoke(() => { }, System.Windows.Threading.DispatcherPriority.Render);
                        }
                    }
                    
                    // Select the final item
                    if (currentTreeItem != null)
                    {
                        currentTreeItem.IsSelected = true;
                        currentTreeItem.BringIntoView();
                    }
                }
            }
            catch (Exception ex)
            {
                // Silently handle errors in tree synchronization
                Console.WriteLine($"Error synchronizing tree view: {ex.Message}");
            }
        }
        
        private void LoadSubfolders(FolderTreeItem parentItem)
        {
            try
            {
                var directories = Directory.GetDirectories(parentItem.FullPath);
                foreach (var dir in directories)
                {
                    var dirInfo = new DirectoryInfo(dir ?? string.Empty);
                    
                    // Skip hidden and system folders
                    if (ShouldHideItem(dirInfo.Name, dirInfo.Attributes))
                        continue;
                    
                    var subFolderItem = new FolderTreeItem
                    {
                        Name = dirInfo.Name,
                        FullPath = dir,
                        Icon = GetSystemIcon(dir, true)
                    };
                    
                    parentItem.Children.Add(subFolderItem);
                }
            }
            catch (UnauthorizedAccessException)
            {
                parentItem.Children.Add(new FolderTreeItem { Name = "访问被拒绝", IsLoaded = true });
            }
            catch (Exception ex)
            {
                parentItem.Children.Add(new FolderTreeItem { Name = $"错误: {ex.Message}", IsLoaded = true });
            }
        }

        private void LoadDirectoryContents(string path)
        {
            try
            {
                var items = new List<FileSystemItem>();

                // Add parent directory option if not at root
                if (Directory.GetParent(path) != null)
                {
                    items.Add(new FileSystemItem
                    {
                        Name = "..",
                        Type = "文件夹",
                        Icon = GetSystemIcon(Directory.GetParent(path)!.FullName, true),
                        Size = "",
                        Modified = "",
                        FullPath = Directory.GetParent(path)!.FullName,
                        IsDirectory = true
                    });
                }

                // Add directories
                var directories = Directory.GetDirectories(path);
                foreach (var dir in directories)
                {
                    var dirInfo = new DirectoryInfo(dir ?? string.Empty);
                    
                    // Skip hidden and system folders
                    if (ShouldHideItem(dirInfo.Name, dirInfo.Attributes))
                        continue;
                    
                    items.Add(new FileSystemItem
                    {
                        Name = dirInfo.Name,
                        Type = "文件夹",
                        Icon = GetSystemIcon(dir, true),
                        Size = "",
                        Modified = dirInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm"),
                        FullPath = dir,
                        IsDirectory = true
                    });
                }

                // Add files
                var files = Directory.GetFiles(path);
                foreach (var file in files)
                {
                    var fileInfo = new FileInfo(file ?? string.Empty);
                    
                    // Skip hidden and system files
                    if (ShouldHideItem(fileInfo.Name, fileInfo.Attributes))
                        continue;
                    
                    items.Add(new FileSystemItem
                    {
                        Name = fileInfo.Name,
                        Type = GetFileType(fileInfo.Extension),
                        Icon = GetSystemIcon(file, false),
                        Size = FormatFileSize(fileInfo.Length),
                        Modified = fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm"),
                        FullPath = file,
                        IsDirectory = false
                    });
                }

                FileListView.ItemsSource = items;
            }
            catch (UnauthorizedAccessException)
            {
                MessageBox.Show($"访问被拒绝: {path}", "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载目录内容时出错: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private bool ShouldHideItem(string name, FileAttributes attributes)
        {
            // Hide items with Hidden or System attributes
            if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden ||
                (attributes & FileAttributes.System) == FileAttributes.System)
            {
                return true;
            }

            // Hide specific system folders and files
            var hiddenItems = new[]
            {
                "$RECYCLE.BIN",
                "System Volume Information",
                "Recovery",
                "pagefile.sys",
                "hiberfil.sys",
                "swapfile.sys",
                "DumpStack.log.tmp",
                "Config.Msi",
                "MSOCache",
                "$WinREAgent",
                "Documents and Settings",
                "Boot",
                "bootmgr",
                "BOOTNXT",
                "BOOTSECT.BAK",
                "Windows.old"
            };

            return hiddenItems.Any(hiddenItem => 
                string.Equals(name, hiddenItem, StringComparison.OrdinalIgnoreCase));
        }

        private void FileListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (FileListView.SelectedItem is FileSystemItem item)
            {
                if (item.IsDirectory)
                {
                    NavigateToPath(item.FullPath);
                    // NavigateToPath already handles updating the address bar and tree view
                }
                else
                {
                    try
                    {
                        System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
                        {
                            FileName = item.FullPath,
                            UseShellExecute = true
                        });
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"无法打开文件: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
                    }
                }
            }
        }

        private string GetFileType(string extension)
        {
            return extension.ToLower() switch
            {
                ".txt" => "文本文件",
                ".pdf" => "PDF文件",
                ".doc" or ".docx" => "Word文档",
                ".xls" or ".xlsx" => "Excel表格",
                ".jpg" or ".jpeg" or ".png" or ".gif" or ".bmp" => "图像",
                ".mp3" or ".wav" or ".flac" => "音频",
                ".mp4" or ".avi" or ".mkv" or ".mov" => "视频",
                ".exe" => "应用程序",
                ".zip" or ".rar" or ".7z" => "压缩文件",
                "" => "文件",
                _ => $"{extension.TrimStart('.')}文件"
            };
        }

        private BitmapSource? GetSystemIcon(string path, bool isDirectory)
        {
            try
            {
                SHFILEINFO shinfo = new SHFILEINFO();
                uint flags = SHGFI_ICON | SHGFI_SMALLICON;
                
                if (isDirectory)
                {
                    flags |= SHGFI_USEFILEATTRIBUTES;
                    SHGetFileInfo(path, FILE_ATTRIBUTE_DIRECTORY, ref shinfo, (uint)Marshal.SizeOf(shinfo), flags);
                }
                else
                {
                    SHGetFileInfo(path, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), flags);
                }

                if (shinfo.hIcon != IntPtr.Zero)
                {
                    BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHIcon(
                        shinfo.hIcon,
                        Int32Rect.Empty,
                        BitmapSizeOptions.FromEmptyOptions());
                    
                    DestroyIcon(shinfo.hIcon);
                    
                    return bitmapSource;
                }
            }
            catch (Exception)
            {
                // Fall back to default icon if extraction fails
            }
            
            return null;
        }

        private string FormatFileSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB", "TB" };
            double len = bytes;
            int order = 0;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len = len / 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }
    }

    public class FileSystemItem
    {
        public string Name { get; set; } = "";
        public string Type { get; set; } = "";
        public BitmapSource? Icon { get; set; }
        public string Size { get; set; } = "";
        public string Modified { get; set; } = "";
        public string FullPath { get; set; } = "";
        public bool IsDirectory { get; set; }
    }

    public class DriveItem
    {
        public string Name { get; set; } = "";
        public string Label { get; set; } = "";
        public BitmapSource? Icon { get; set; }
    }
    
    public class FolderTreeItem
    {
        public string Name { get; set; } = "";
        public string FullPath { get; set; } = "";
        public BitmapSource? Icon { get; set; }
        public ObservableCollection<FolderTreeItem> Children { get; set; } = new ObservableCollection<FolderTreeItem>();
        public bool IsLoaded { get; set; } = false;
        
        // Placeholder for lazy loading
        public FolderTreeItem()
        {
            // Add a dummy item to show expand button
            Children.Add(new FolderTreeItem { Name = "Loading..." });
        }
    }
}
